When a user visits a non-pre-generated route, behavior is controlled by the dynamicParams export: true generates the page on-demand and caches it, false returns 404, and omitted defaults to true in App Router
In Next.js App Router, when a user navigates to a dynamic route that wasn't pre-generated by generateStaticParams, the behavior is determined by the dynamicParams export. This setting controls whether Next.js should generate pages on-demand when they're first requested. With dynamicParams: true (default), Next.js will generate the page on the first visit and cache it for subsequent requests. With dynamicParams: false, any non-pre-generated path returns a 404. This gives developers fine-grained control over the trade-off between build time and user experience.
If you don't explicitly set dynamicParams, it defaults to true. This means when a user requests a path that wasn't included in your generateStaticParams return array, Next.js will generate the page on-demand (server-side render it), cache the result, and serve it to the user. Future requests for the same path will be served from cache. This is perfect for large sites where you can't pre-render everything at build time—you pre-render popular paths and let long-tail content generate as users request it .
When you set dynamicParams: false, you're telling Next.js that your generateStaticParams function returns an exhaustive list of all possible paths. Any path not included should return a 404 page. This is ideal for sites with a known, fixed set of content—like a blog with a finite number of posts that you can generate at build time. It provides the best performance (all pages are static) and ensures that users never encounter a slow first-visit generation, but it requires that you know all possible paths at build time .
dynamicParams: true in App Router corresponds to fallback: true or fallback: 'blocking' in Pages Router, depending on whether you use Suspense .
dynamicParams: false directly corresponds to fallback: false in Pages Router .
The main difference is that App Router's dynamicParams: true combines both the loading state (with Suspense) and blocking behavior, whereas Pages Router had separate true and 'blocking' options .
In App Router, you control the loading experience with loading.tsx files, which automatically provide Suspense boundaries for on-demand generated pages .
dynamicParams works alongside the revalidate export. When dynamicParams: true and you set revalidate: 3600, on-demand generated pages will also follow the revalidation schedule—they'll be regenerated in the background after 3600 seconds just like pre-rendered pages . This means long-tail content isn't second-class; it gets the same ISR benefits as popular content. When dynamicParams: false, the revalidate setting only applies to pre-generated pages; non-generated paths are permanently 404 and never revalidated.
When dynamicParams: true and a user hits an ungenerated route, Next.js server-renders the page on the fly. The user sees the page (maybe with a loading state if you've implemented Suspense), and the resulting HTML is cached. Importantly, this generation happens synchronously for the first user—they might experience a slightly slower page load while the server fetches data and renders. Subsequent users get the cached static version. If you want to avoid this first-visit slowdown, you can either pre-render more paths or implement a loading skeleton with loading.tsx that shows immediately while generation happens in the background .
Use dynamicParams: false when: You have a fixed, known set of content (e.g., 100 blog posts, 50 documentation pages) and can generate all paths at build time .
Use dynamicParams: true when: You have a large or unbounded content set (e.g., e-commerce with thousands of products, user-generated content) and want to balance build time with user experience .
Consider adding loading.tsx when: Using dynamicParams: true to provide immediate visual feedback during first-visit generation .
Monitor on-demand generation frequency: If certain paths are rarely visited, they may never be generated, which is fine—they'll generate on first request and then be cached .